package com.gome.ocean.service.gddl.impl;

import java.util.*;

import javax.mail.MessagingException;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gome.framework.AppContext;
import com.gome.framework.Env;
import com.gome.ocean.common.enums.DataSourceStatus;
import com.gome.ocean.common.utils.TimeUtils;
import com.gome.ocean.dao.gddl.GroupRuleDAO;
import com.gome.ocean.dao.model.authority.ProjectBO;
import com.gome.ocean.dao.model.diamond.ConfigInfoBO;
import com.gome.ocean.dao.model.gddl.AppBO;
import com.gome.ocean.dao.model.gddl.AppDatasourceBO;
import com.gome.ocean.dao.model.gddl.GroupBO;
import com.gome.ocean.dao.model.gddl.GroupRuleBO;
import com.gome.ocean.service.authority.ProjectService;
import com.gome.ocean.service.diamond.ConfigInfoService;
import com.gome.ocean.service.gddl.AppDatasourceService;
import com.gome.ocean.service.gddl.AppService;
import com.gome.ocean.service.gddl.GroupRuleService;
import com.gome.ocean.service.mail.EmailConstants;
import com.gome.ocean.service.mail.EmailSubject;
import com.gome.ocean.service.mail.SimpleMailSender;
import com.taobao.tddl.group.jdbc.TGroupDataSource;

@Service("groupRuleService")
@Transactional("transactionManager")
public class GroupRuleServiceImpl implements GroupRuleService {

    private static final Logger  LOG = LoggerFactory.getLogger(GroupRuleServiceImpl.class);
    @Autowired
    private ConfigInfoService    configInfoService;
    @Autowired
    private AppService           appService;
    @Autowired
    private SimpleMailSender     simpleMailSender;
    @Autowired
    private GroupRuleDAO         groupRuleDAO;
    @Autowired
    private ProjectService       projectService;
    @Autowired
    private AppDatasourceService appDatasourceService;

    @Override
    public boolean insertGroupRuleBO(GroupRuleBO groupRuleBO) {
        return groupRuleDAO.insertGroupRuleBO(groupRuleBO) > 0;
    }

    @Override
    public boolean removeGroupRuleBOById(Long id) {
        return groupRuleDAO.removeGroupRuleBOById(id) > 0;
    }

    @Override
    public boolean updateGroupRuleBOById(GroupRuleBO groupRuleBO) {
        return groupRuleDAO.updateGroupRuleBOById(groupRuleBO) > 0;
    }

    @Override
    public GroupRuleBO findGroupRuleBOById(Long id) {
        return groupRuleDAO.findGroupRuleBOById(id);
    }

    @Override
    public GroupRuleBO findGroupRuleBOByIdAndName(Long groupId, String groupRuleName) {
        return groupRuleDAO.findGroupRuleBOByIdAndName(groupId, groupRuleName);
    }

    @Override
    public List<GroupRuleBO> findGroupRuleBOByGroupId(Long groupId) {
        return groupRuleDAO.findGroupRuleBOByGroupId(groupId);
    }

    @Override
    public boolean switchBackUpDb(GroupBO groupBO, List<GroupRuleBO> groupRuleBOs) {

        GroupRuleBO currentGroupRule = null;
        GroupRuleBO switchGroupRule = null;
        Iterator<GroupRuleBO> iterator = groupRuleBOs.iterator();
        // userinfo_hash_8306_1:w10r10,userinfo_hash_8306_2:b
        StringBuffer newContent = new StringBuffer();
        while (iterator.hasNext()) {
            GroupRuleBO groupRuleBO = iterator.next();
            if (groupRuleBO.getIsBak() == 1) {
                switchGroupRule = groupRuleBO;
                newContent.append(groupRuleBO.getGroupRuleName()).append(":").append("w10r10").append(",");
            } else {
                currentGroupRule = groupRuleBO;
                newContent.append(groupRuleBO.getGroupRuleName()).append(":").append("b").append(",");
            }
        }
        newContent = newContent.deleteCharAt(newContent.length() - 1);

        ConfigInfoBO fullGroupInfo = configInfoService
            .findConfigInfoBOByDataId(TGroupDataSource.getFullDbGroupKey(groupBO.getGroupName()));
        String groupContent = fullGroupInfo.getContent();
        if (StringUtils.isEmpty(groupContent)) {
            return Boolean.FALSE;
        }
        String[] dsWeights = StringUtils.split(groupContent, ",");
        if (dsWeights.length < 2) {
            return Boolean.FALSE;
        }

        AppDatasourceBO appDatasourceBO = appDatasourceService
            .findAppDatasourceBOById(switchGroupRule.getDatasourceId());
        if (currentGroupRule == null && switchGroupRule == null || appDatasourceBO == null) {
            return Boolean.FALSE;
        }
        DataSourceStatus dataSourceStatus = DataSourceStatus.getDataSourceStatus(appDatasourceBO.getSourceStatus());
        if (DataSourceStatus.ERROR == dataSourceStatus) {
            LOG.info("backed db status is error ignore !");
            return Boolean.FALSE;
        }

        fullGroupInfo.setContent(newContent.toString());
        boolean result = configInfoService.updateConfigInfoBOById(fullGroupInfo);
        if (result) {
            // notifyService.notifyConfigInfoChange(fullGroupInfo.getDataId(),fullGroupInfo.getGroupId(),MD5.getInstance().getMD5String(newContent.toString()));
            sendSwitchDbMail(groupBO, currentGroupRule, switchGroupRule);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 发送报警邮件
     * 
     * @param appDatasourceBO
     */
    private void sendSwitchDbMail(GroupBO groupBO, GroupRuleBO currentGroupRule, GroupRuleBO switchGroupRule) {
        try {
            Env envVal = AppContext.getEnv();
            String mailAlarmNotifiPersons = envVal.get("mail_alarm_notification");
            AppBO appBO = appService.findAppBOById(groupBO.getAppId());
            if (appBO != null) {
                List<String> recipients = Arrays.asList(StringUtils.split(mailAlarmNotifiPersons, ","));
                Map<String, String> contextMaps = new HashMap<String, String>();
                contextMaps.put("APPNAME", appBO.getAppName());
                contextMaps.put("DBNAME",
                    "主库【" + currentGroupRule.getGroupRuleName() + "】备库【" + switchGroupRule.getGroupRuleName() + "】");
                contextMaps.put("DATE", TimeUtils.timestampToToday());
                AppDatasourceBO currentDatasource = appDatasourceService
                    .findAppDatasourceBOById(currentGroupRule.getDatasourceId());
                AppDatasourceBO switchDatasource = appDatasourceService
                    .findAppDatasourceBOById(switchGroupRule.getDatasourceId());
                contextMaps.put("ALERTCONTEXT",
                    EmailConstants.DEFAULT_SWITCH_DB_MESSAGE
                        .format(new Object[] { currentDatasource.getJdbcUrl(), switchDatasource.getJdbcUrl() }));
                contextMaps.put("PROJECT", EmailConstants.DEFAULT_PROJECT);
                simpleMailSender.send(recipients, EmailSubject.SWITCHDB, contextMaps);
            }
        } catch (MessagingException e) {
            LOG.error("send alert mail is error! " + e);
        }
        LOG.info("GDDL数据源切换成功!源数据" + currentGroupRule.getGroupRuleName() + ",切换到" + switchGroupRule.getGroupRuleName());
    }

    @Override
    public GroupRuleBO findGroupRuleBOByName(String groupRuleName) {
        return groupRuleDAO.findGroupRuleBOByName(groupRuleName);
    }

    @Override
    public List<GroupRuleBO> getGroupRuleInfoByMap(Map<String, Object> map) {
        if (map != null && map.size() > 0) {
            List<GroupRuleBO> groupRule = groupRuleDAO.getGroupRuleInfoByMap(map);
            return groupRule;
        }
        return null;
    }
}
